#pragma once
/*本文件实现httpServer的核心内容*/

#include "logMessage.hpp"
#include "threadPool.hpp"
using namespace threadpool;
#include "Task.hpp"
#include "httpProtocol.hpp"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <functional>
#include <unordered_map>

/*网络必要头文件*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

enum
{
    SOCKET_ERROR = 1,
    BIND_ERROR,
    LISTEN_ERROR,
    ACCEPT_ERROR,
    RECV_ERROR
};

typedef function<bool(httpRequest &,httpResponse &)> func_t;
class httpServer
{
public:
    httpServer(const func_t func,const uint16_t &serverPort)
        : _listenSocketFd(-1), _serverPort(serverPort),_func(func)
    {
        _tp.start();
    }
    ~httpServer()
    {
        close(_listenSocketFd);
    }

    /*初始化服务器*/
    void initServer()
    {
        _listenSocketFd = socket(AF_INET, SOCK_STREAM, 0); /*TCP*/
        if (_listenSocketFd == -1)
        {
            logMessage(FATAL, "listen socket create failed,return value[%d]", _listenSocketFd);
            exit(SOCKET_ERROR);
        }
        logMessage(NORMAL, "listen socket create success,return value[%d]", _listenSocketFd);

        /*绑定本地套接字*/
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_serverPort);
        local.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_listenSocketFd, (struct sockaddr *)&local, sizeof(local));
        if (n == -1)
        {
            logMessage(FATAL, "bind failed,return value[%d]", n);
            exit(BIND_ERROR);
        }
        logMessage(NORMAL, "bind success,return value[%d]", n);

        /*开始监听*/
        n = listen(_listenSocketFd, gBacklog);
        if (n == -1)
        {
            logMessage(FATAL, "listen failed,return value[%d]", n);
            exit(LISTEN_ERROR);
        }
        logMessage(NORMAL, "listen success,return value[%d]", n);
    }

    /*正式启动服务器*/
    void start()
    {
        while (true)
        {
            struct sockaddr_in client; /*该结构体做accept的输出型参数，用来获取客户端的套接字*/
            socklen_t len = sizeof(client);
            int sock = accept(_listenSocketFd, (struct sockaddr *)&client, &len);
            if (sock == -1)
            {
                logMessage(FATAL, "accept failed,return value[%d]", sock);
                exit(ACCEPT_ERROR);
            }
            logMessage(NORMAL, "accept success,return value[%d]", sock);

            /*开始对链接过来的客户端做处理*/
            _tp.push(Task(sock,_func/*,_hashCallBack*/));
        }
    }

    // void registerCallBack(const std::string &parm,const func_t &func)
    // {
    //     _hashCallBack.insert(std::make_pair(parm,func));
    // }

private:
    int _listenSocketFd; /*监听套接字文件描述符*/
    uint16_t _serverPort;
    static const int gBacklog = 10;
    threadPool<Task> _tp;/*线程池*/
    func_t _func;
    //std::unordered_map<std::string, func_t> _hashCallBack;
};